package com.ssy.lingxi.sms.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.sms.api.common.AliConfigEnum;
import com.ssy.lingxi.sms.api.common.ServiceTypeEnum;
import com.ssy.lingxi.sms.api.common.StatusEnum;
import com.ssy.lingxi.sms.api.common.TencentConfigEnum;
import com.ssy.lingxi.sms.api.model.SmsConfigVO;
import com.ssy.lingxi.sms.api.model.request.TemplateRequest;
import com.ssy.lingxi.sms.entity.SmsConfig;
import com.ssy.lingxi.sms.entity.Template;
import com.ssy.lingxi.sms.repository.SmsConfigRepository;
import com.ssy.lingxi.sms.repository.TemplateRepository;
import com.ssy.lingxi.sms.service.ISmsConfigService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.HashMap;
import java.util.List;

/**
 * 短信发送类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/10
 */
@Service
public class SmsConfigServiceImpl implements ISmsConfigService {

    @Autowired
    private SmsConfigRepository smsConfigRepository;

    @Autowired
    private TemplateRepository templateRepository;

    @Autowired
    private IRedisStringUtils redisStringUtils;

    /**
     * 查询配置信息
     * @return SmsConfig
     */
    @Override
    public SmsConfig getSmsConfig(Integer serviceType){
        return smsConfigRepository.findTopByServiceTypeOrderByIdDesc(serviceType);
    }

    /**
     * 查询生效的配置信息
     * @return SmsConfig
     */
    @Override
    public SmsConfig findEnableSmsConfig(){
        SmsConfig smsConfig = null;
        //先从redis缓存中查找配置信息
        String json = redisStringUtils.hGet(Constants.REDIS_KEY_SERVICE, Constants.REDIS_FIELD_SERVICE_CONFIG, Constants.REDIS_SMS_INDEX);
        if(StringUtils.isNotEmpty(json)){
            smsConfig = JSONUtil.toBean(json,SmsConfig.class);
        }
        //redis缓存中获取不到配置信息，则从数据库中查找
        if (smsConfig == null) {
            smsConfig = smsConfigRepository.findSmsConfigByStatus(StatusEnum.ENABLED.getCode());
        }
        return smsConfig;
    }

    /**
     * 添加/修改短信服务器配置
     * @param smsConfigVO
     * @return
     */
    @Transactional
    @Override
    public Boolean saveOrUpdateSmsConfig(SmsConfigVO smsConfigVO){
        Integer serviceType = smsConfigVO.getServiceType();
        String code = smsConfigVO.getCode();
        String value = smsConfigVO.getValue();
        String remark = smsConfigVO.getRemark();

        //校验参数代码是否合法
        Boolean flag = checkLegal(serviceType, code);
        if(!flag){
            throw new BusinessException(ResponseCode.SMS_CONFIG_UNLEGAL);
        }
        //查询数据库是否存在该数据
        HashMap<String,Object> configMap;
        SmsConfig smsConfig = smsConfigRepository.findTopByServiceTypeOrderByIdDesc(serviceType);
        if(smsConfig == null){
            configMap = new HashMap<>();
            smsConfig = new SmsConfig();
            smsConfig.setServiceType(serviceType);
        }else{
            configMap = smsConfig.getConfig();
        }
        configMap.put(code, value + "|" + remark);
        smsConfig.setConfig(configMap);
        smsConfig.setStatus(true);
        //数据库持久化对象
        smsConfigRepository.saveAndFlush(smsConfig);
        smsConfigRepository.stopOthersConfig(smsConfig.getId());

        //只有启用的情况才需要将最新配置存入redis缓存中
        boolean status = smsConfig.getStatus();
        if(status){
            redisStringUtils.hSet(Constants.REDIS_KEY_SERVICE, Constants.REDIS_FIELD_SERVICE_CONFIG , JSONUtil.toJsonStr(smsConfig), Constants.REDIS_SMS_INDEX);
        }
        return true;
    }

    /**
     * 删除短信服务器配置
     * @param serviceType
     * @param code
     * @return
     */
    @Override
    public Boolean deleteSmsConfig(Integer serviceType, String code) {
        //校验参数代码是否合法
        Boolean flag = checkLegal(serviceType, code);
        if(!flag){
            throw new BusinessException(ResponseCode.SMS_CONFIG_UNLEGAL);
        }
        //查询数据库是否存在该数据
        SmsConfig smsConfig = smsConfigRepository.findTopByServiceTypeOrderByIdDesc(serviceType);
        if(smsConfig != null){
            HashMap<String,Object> configMap = smsConfig.getConfig();
            if(configMap != null && configMap.containsKey(code)){
                configMap.remove(code);
                smsConfig.setConfig(configMap);

                //数据库持久化对象
                smsConfigRepository.saveAndFlush(smsConfig);

                //只有启用的情况才需要将最新配置存入redis缓存中
                boolean status = smsConfig.getStatus();
                if(status){
                    redisStringUtils.hSet(Constants.REDIS_KEY_SERVICE, Constants.REDIS_FIELD_SERVICE_CONFIG , JSONUtil.toJsonStr(smsConfig), Constants.REDIS_SMS_INDEX);
                }
                return true;
            }else{
                throw new BusinessException(ResponseCode.SMS_CONFIG_CODE_NOT_EXIST);
            }
        }else{
            throw new BusinessException(ResponseCode.SMS_CONFIG_NOT_EXIST);
        }
    }

    /**
     * 校验参数代码是否正确
     * @param serviceType 服务商类型: 1-腾讯云，2-阿里云
     * @param code 配置参数名
     * @return 是否正确
     */
    private Boolean checkLegal(Integer serviceType, String code){
        if(serviceType.equals(ServiceTypeEnum.Tencent.getCode())){
            return TencentConfigEnum.getMessage(code);
        }else if(serviceType.equals(ServiceTypeEnum.Ali.getCode())){
            return AliConfigEnum.getMessage(code);
        }
        return false;
    }

    /**
     * 启用/停用短信服务器
     * @param serviceType
     * @return
     */
    @Override
    @Transactional
    public Boolean updateSmsConfigStatus(Integer serviceType){
        //验证数据库中是否存在该数据
        SmsConfig smsConfig = smsConfigRepository.findTopByServiceTypeOrderByIdDesc(serviceType);
        if(smsConfig == null){
            throw new BusinessException(ResponseCode.SMS_CONFIG_NOT_EXIST);
        }

        //持久化数据
        smsConfig.setStatus(true);
        smsConfigRepository.saveAndFlush(smsConfig);

        //只能启用一个配置，所以停掉其他的
        smsConfigRepository.stopOthersConfig(smsConfig.getId());

        //将最新配置存入redis缓存中
        redisStringUtils.hSet(Constants.REDIS_KEY_SERVICE, Constants.REDIS_FIELD_SERVICE_CONFIG , JSONUtil.toJsonStr(smsConfig), Constants.REDIS_SMS_INDEX);
        return true;
    }

    /**
     * 查询短信内容模板
     * @return
     */
    @Override
    public Page<Template> getSmsTemplateList(Pageable page) {
        return templateRepository.findAll(page);
    }

    /**
     * 新增/修改短信内容模板
     * @return
     */
    @Override
    public Boolean saveOrUpdateSmsTemplate(TemplateRequest templateVO){
        String code = templateVO.getCode();
        List<Template> templateList = templateRepository.findByCode(code);
        Template template;
        if(templateList != null && !templateList.isEmpty()){
            template = templateList.get(0);
        }else{
            template = new Template();
        }
        //保存数据
        CopyOptions copyOptions = new CopyOptions();
        copyOptions.setIgnoreProperties("id");
        BeanUtil.copyProperties(templateVO, template, copyOptions);
        template.setInternational(0L);
        template.setSmsType(0L);
        template.setStatusCode(0L);
        templateRepository.saveAndFlush(template);

        return true;
    }

    /**
     * 删除短信内容模板
     * @return
     */
    @Override
    public Boolean deleteSmsTemplate(Long id){
        if(id != null){
            Template template = templateRepository.findById(id).orElse(null);
            if(template != null){
                //删除数据库中的短信内容模板
                templateRepository.deleteTemplateById(id);
                return true;
            }
        }
        return false;
    }

    /**
     * 清空短信内容模板
     * @return
     */
    @Override
    public Boolean clearSmsTemplate() {
        smsConfigRepository.deleteAllInBatch();
        templateRepository.deleteAllInBatch();
        return true;
    }
}

